package fatworm.parser;
@SuppressWarnings("unused")

%% 
%unicode
%class Lexer
%cup
%cupdebug
%char
%public 
%ignorecase


%state STRING

%{

private void error( String s ) {
	throw new java.lang.RuntimeException( (yychar - yytext().length())+":" + s );
}
private java_cup.runtime.Symbol token(int id,int leftpos,Object value) {    
	return new java_cup.runtime.Symbol( id , leftpos , yychar+-yytext().length() , value );
}
private java_cup.runtime.Symbol token(int id, Object value) {    
	return new java_cup.runtime.Symbol( id , yychar, yychar+-yytext().length(), value );
}
private java_cup.runtime.Symbol token(int id) {    
	return new java_cup.runtime.Symbol( id , yychar, yychar+-yytext().length() , null );
}

private StringBuffer stringBuf = new StringBuffer();
private int stringStart;

%}



/* Macro define */
LineTerminator 	= \r|\n|\r\n
WhiteSpace 		= [ \t\f]
Identifier		= [a-zA-Z][a-zA-Z0-9_]*
DecInteger 	 	= 0 | [0-9][0-9]*

StringCharacter = [^\r\n\'\\]

/* floating point literals , code from jflex examples */  
FLit1    = [0-9]+ \. [0-9]* 
FLit2    = \. [0-9]+ 
FLit3    = [0-9]+ 
Exponent = [eE] [+-]? [0-9]+      
DoubleLiteral = ({FLit1}|{FLit2}|{FLit3}) {Exponent}?

%%

<YYINITIAL> {
	{WhiteSpace}		{ /* do nothing */ }
	{LineTerminator}	{ /* do nothing */ }
	/* Token : reserved words */
	"create"|"CREATE"  		{ return token(sym.CREATE); }
	"use"|"USE"          { return token(sym.USE); }
	"drop"	|"DROP"  		{ return token(sym.DROP); }
	"insert"|"INSERT"  		{ return token(sym.INSERT); }	
	"into"	|"INTO"  		{ return token(sym.INTO); }			
	"select"|"SELECT"  		{ return token(sym.SELECT); }
	"delete"|"DELETE"  		{ return token(sym.DELETE); }
	"from"	|"FROM"  		{ return token(sym.FROM); }				
	"on"	|"ON"  			{ return token(sym.ON); }
	"update"|"UPDATE"  		{ return token(sym.UPDATE); }
	"set"	|"SET"  		{ return token(sym.SET); }
	"database"|"DATABASE"	{ return token(sym.DATABASE); }
	"table"	|"TABLE"		{ return token(sym.TABLE); }
	"index"	|"INDEX"		{ return token(sym.INDEX); }
	"values"|"VALUES"		{ return token(sym.VALUES); }
	"unique"|"UNIQUE"		{ return token(sym.UNIQUE); }
	"primary"|"PRIMARY"		{ return token(sym.PRIMARY); }
	"key"	|"KEY"			{ return token(sym.KEY); }	
	"null"	|"NULL"			{ return token(sym.NULL); }		
	"default"|"DEFAULT"		{ return token(sym.DEFAULT); }
	"auto_increment"|"AUTO_INCREMENT"	{ return token(sym.AUTO_INCREMENT); }
	"int"	|"INT"			{ return token(sym.INT); }
	"float"	|"FLOAT"		{ return token(sym.FLOAT); }		
	"datetime"|"DATETIME"	{ return token(sym.DATETIME); }
	"boolean"|"BOOLEAN"		{ return token(sym.BOOLEAN); }
	"decimal"|"DECIMAL"		{ return token(sym.DECIMAL); }	
	"timestamp"|"TIMESTAMP"	{ return token(sym.TIMESTAMP); }	
	"varchar"|"VARCHAR"		{ return token(sym.VARCHAR); }			
	"char"	|"CHAR"			{ return token(sym.CHAR); }		
	"distinct"|"DISTINCT"	{ return token(sym.DISTINCT); }	
	"where"	|"WHERE"		{ return token(sym.WHERE); }	
	"group"	|"GROUP"		{ return token(sym.GROUP); }
	"order"	|"ORDER"		{ return token(sym.ORDER); }
	"by"	|"BY"			{ return token(sym.BY); }	
	"having"|"HAVING"		{ return token(sym.HAVING); }		
	"asc"	|"ASC"			{ return token(sym.ASC); }
	"desc"	|"DESC"			{ return token(sym.DESC); }
	"as"	|"AS"			{ return token(sym.AS); }
	"and"	|"AND"			{ return token(sym.AND); }
	"or"	|"OR"			{ return token(sym.OR); }
	"not"	|"NOT"			{ return token(sym.NOT); }
	"exists"|"EXISTS"		{ return token(sym.EXISTS); }	
	"any"	|"ANY"			{ return token(sym.ANY); }			
	"in"	|"IN"			{ return token(sym.IN); }
	"all"	|"ALL"			{ return token(sym.ALL); }
	"true"  |"TRUE"			{ return token(sym.TRUE); }
	"false" |"FALSE"		{ return token(sym.FALSE); }
			
	/* operators */		
	">="					{ return token(sym.GE); }	
	">"						{ return token(sym.GT); }
	"<="					{ return token(sym.LE); }
	"<"						{ return token(sym.LT); }	
	"="						{ return token(sym.EQ); }
	"<>"					{ return token(sym.NE); }
	"+"						{ return token(sym.ADD); }
	"-"						{ return token(sym.SUB); }
	"*"						{ return token(sym.MUL); }
	"/"						{ return token(sym.DIV); }
	"%"						{ return token(sym.MOD); }
	"("						{ return token(sym.LPAREN); }
	")"						{ return token(sym.RPAREN); }
	"."						{ return token(sym.DOT); }		
	","						{ return token(sym.COMMA); }
	
	
	/* aggregate functions */
	"sum"	|"SUM"			{ return token(sym.SUM , new String("sum") ); }
	"avg"	|"AVG"			{ return token(sym.AVG , new String("avg") ); }
	"count"	|"COUNT"		{ return token(sym.COUNT , new String("count") ); }
	"max"	|"MAX"			{ return token(sym.MAX , new String("max") ); }
	"min"	|"MIN"			{ return token(sym.MIN , new String("min") ); }
	
	/* Identifier */
	{Identifier} { return token(sym.ID, yytext()); }
	
	{DecInteger} { 
		int val = 0;
		try{
	 		val = Integer.parseInt(yytext());
		}catch( java.lang.NumberFormatException e ){
			return token( sym.DECIMAL_CONST , yytext() ); 
		}
		return token( sym.INT_CONST , new Integer(val) ); 
	}
	
	{DoubleLiteral} { 
		try{
			return token( sym.FLOAT_CONST, new Double(yytext()) ); 
		}catch( java.lang.NumberFormatException e ){
			return token( sym.DECIMAL_CONST , yytext() );
		}
	}	
	
	
	"\'"	{ yybegin(STRING); stringBuf.setLength(0); stringStart = yychar;}
	 																																						
	<<EOF>>{ return token(sym.EOF); }
	[^] { error("Illigal character \"" +  yytext()+"\""); }
}


<STRING> {
	"\'"	{ yybegin(YYINITIAL); return token(sym.STRING,stringStart, stringBuf.toString() ); }
	
	{StringCharacter}+ { stringBuf.append(yytext());}
	
	/* escape sequences*/
	"\\n"	{ stringBuf.append('\n'); }
	"\\t"	{ stringBuf.append('\t'); }
	"\\\\"	{ stringBuf.append('\\'); }
	"\\\'"  { stringBuf.append('\''); }
	
	/* errors */
	{LineTerminator} { error("Unterminated string at end of line");  } 

	<<EOF>>{ error("Unfinished string at the end of file"); return token(sym.error); }	               
	\\.				 { error("Illegal escape sequence \""+yytext()+"\""); }
}
